package com.han.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * JSON转换工具类
 * 
 * @date 2010-11-23
 * @since JDK 1.5
 * @author dingkui
 * @version 1.0
 * 
 */
public class JsonUtil {

    /**
     * 
     */
    public static final ObjectMapper mapper= new ObjectMapper();

//    static {
//        JsonUtil.mapper = new ObjectMapper();
//    }

    /**
     * 将object转为json字符串
     * 
     * @param pObj
     *      参数
     * @throws IOException
     *      异常
     * @throws JsonMappingException
     *      异常
     * @throws JsonGenerationException
     *      异常
     * @return String
     */
    public static String writeValue(Object pObj) throws JsonGenerationException, JsonMappingException, IOException {
        return JsonUtil.mapper.writeValueAsString(pObj);
    }

    /**
     * 将content转为java object
     * 
     * @param <T>
     *      参数
     * @param pContent
     *      参数
     * @param pObj
     *      参数
     * @throws JsonParseException
     *      异常
     * @throws JsonMappingException
     *      异常
     * @throws IOException
     *      异常
     * @return Object
     */
    @SuppressWarnings("unchecked")
    public static <T> Object readValue(String pContent, Object pObj) throws JsonParseException, JsonMappingException,
            IOException {
        return JsonUtil.mapper.readValue(pContent, (Class<T>) pObj);
    }
    
	/**
	 * 将json格式的字符串转换为javabean
	 * 
	 * @param jsonStr
	 * @param beanClazz
	 * @return
	 * @throws Exception
	 */
	public static <T> T readBean(String jsonStr, Class<T> beanClazz)
			throws Exception {
		if (StringUtils.isBlank(jsonStr)) {
			return null;
		}
		JSONObject jsObj = JSONObject.parseObject(jsonStr);
		return jsObjToBean(jsObj, beanClazz);
	}

	@SuppressWarnings("unchecked")
	public static <T> T jsObjToBean(JSONObject jsObj, Class<T> beanClazz)
			throws Exception {
		T bean = beanClazz.newInstance();
		Method[] pubMethods = beanClazz.getMethods();
		outer: for (String jsPropKey : jsObj.keySet()) {
			Object jsPropValue = jsObj.get(jsPropKey);
			if (jsPropValue == null) {
				continue;
			}
			String jsPropName = jsPropKey;
			if (jsPropName.indexOf('_') >= 0) {
				jsPropName = StringUtils.replace(jsPropName, "_", "");
			}
			for (Method pubMethod : pubMethods) {
				if (pubMethod.getName().equalsIgnoreCase("set" + jsPropName)) {
					Class<?> beanPropClazz = pubMethod.getParameterTypes()[0];
					Object beanPropValue = null;
					if (jsPropValue instanceof JSONObject) {
						beanPropValue = jsObjToBean((JSONObject) jsPropValue,
								beanPropClazz);
					} else if (jsPropValue instanceof JSONArray) {
						if (beanPropClazz != List.class
								&& beanPropClazz != ArrayList.class) {
							throw new RuntimeException("目前只支持List属性");
						}
						ParameterizedType args = (ParameterizedType) (pubMethod
								.getGenericParameterTypes()[0]);
						Class<?> actuClazz = (Class<?>) args
								.getActualTypeArguments()[0];
						beanPropValue = new ArrayList<Object>();
						JSONArray jskjArray = (JSONArray) jsPropValue;
						if (!jskjArray.isEmpty()) {
							for (int i = 0; i < jskjArray.size(); i++) {
								if (jskjArray.get(i).getClass() == JSONObject.class) {
									((List<Object>) beanPropValue)
											.add(jsObjToBean(
													(JSONObject) (jskjArray
															.get(i)), actuClazz));
								}
							}
						}
					} else if (beanPropClazz == String.class) {
						beanPropValue = jsObj.getString(jsPropKey);
					} else if (StringUtils.isBlank(jsObj.getString(jsPropKey))) {
						continue outer;
					} else if (Number.class.isAssignableFrom(beanPropClazz)) {
						beanPropValue = beanPropClazz.getConstructor(
								String.class).newInstance(
								jsObj.getString(jsPropKey));
					} else if (beanPropClazz == Date.class) {
						beanPropValue = DateUtil.getDate(jsObj
								.getString(jsPropKey));
					} else if (beanPropClazz == int.class) {
						beanPropValue = Integer.parseInt(jsObj
								.getString(jsPropKey));
					} else if (beanPropClazz == byte.class) {
						beanPropValue = Byte.parseByte(jsObj
								.getString(jsPropKey));
					} else if (beanPropClazz == float.class) {
						beanPropValue = Float.parseFloat(jsObj
								.getString(jsPropKey));
					} else if (beanPropClazz == double.class) {
						beanPropValue = Double.parseDouble(jsObj
								.getString(jsPropKey));
					} else if (beanPropClazz == short.class) {
						beanPropValue = Short.parseShort(jsObj
								.getString(jsPropKey));
					} else {
						throw new RuntimeException("不支持的数据类型:"
								+ jsPropValue.getClass().getName() + " "
								+ beanPropClazz);
					}
					pubMethod.invoke(bean, beanPropValue);
				}
			}
		}
		return bean;
	}

	/**
	 * 将json格式的字符串转换为javabean的List
	 * 
	 * @param jsonStr
	 * @param beanClazz
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> readBeanList(String jsonStr, Class<T> beanClazz)
			throws Exception {
		if (StringUtils.isBlank(jsonStr)) {
			return null;
		}
		List<T> beanList = new ArrayList<T>();
		JSONArray jsArray = JSONObject.parseArray(jsonStr);
		if (!jsArray.isEmpty()) {
			for (int i = 0; i < jsArray.size(); i++) {
				beanList.add(jsObjToBean((JSONObject) (jsArray.get(i)),
						beanClazz));
			}
		}
		return beanList;
	}
}
